package com.itheima.tanhua.server.controller;

import cn.hutool.core.util.RandomUtil;
import com.itheima.commons.holder.TokenHolder;
import com.itheima.commons.utils.JwtUtils;
import com.itheima.tanhua.dubbo.api.UserService;
import com.itheima.tanhua.model.domain.User;
import com.itheima.tanhua.model.domain.UserInfo;
import com.itheima.tanhua.model.dto.LoginDto;
import com.itheima.tanhua.model.dto.LoginReginfoDto;
import com.itheima.tanhua.model.dto.LoginVerificationDto;
import com.itheima.tanhua.model.vo.LoginVerificationVo;
import com.itheima.tanhua.server.template.AipTemplate;
import com.itheima.tanhua.autoconfig.template.OssTemplate;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author itheima
 * @since 2022-03-03
 */
@RestController
@RequestMapping("user")
public class UserController {

    @Autowired
    private RedisTemplate redisTemplate;

    @DubboReference
    private UserService userService;

    @Autowired
    private AipTemplate aipTemplate;

    @Autowired
    private OssTemplate ossTemplate;

    @PostMapping("/login")
    public ResponseEntity login(@RequestBody LoginDto dto) {
        // 第一步：获取用户的手机号
        String phone = dto.getPhone();

        // 第二步：生成4位验证码（使用hutool工具类）
        String verifyCode = RandomUtil.randomNumbers(6);

        System.out.println(verifyCode);

        // 第三步：发送验证码（略过）

        // 如果有人不断刷你的接口，你怎么处理？

        // 第四步：验证码写入redis，并设置过期时间
        // 过期时间设置多久比较合适？可以观察其他APP的做法
        // 项目名 _ 功能名称

        redisTemplate.opsForValue().set("tanhua_verify_code:" + phone, verifyCode, 3600, TimeUnit.SECONDS);

        // 第五步：使用统一的返回值结构
        return ResponseEntity.ok(null);
    }


    @PostMapping("/loginVerification")
    public ResponseEntity loginVerification(@RequestBody LoginVerificationDto dto) throws Exception {
        // 第一步：获取用户的手机和验证码
        String phone = dto.getPhone();
        String verificationCode = dto.getVerificationCode();

        // 定义redis的key
        String redisKey = "tanhua_verify_code:" + phone;

        // 第二步：获取原先发送的验证码
        String code = (String) redisTemplate.opsForValue().get(redisKey);

        // 返回错误
        if (StringUtils.isEmpty(verificationCode) || StringUtils.isEmpty(phone)) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("手机号或验证码不能为空");
        }

        // 第三步：将原先的验证码和用户发过来的验证码进行比对
        if (!verificationCode.equals(code)) {
            throw new Exception("验证码失效");
        }

        // 删除验证码缓存
        redisTemplate.delete(redisKey);

        // 根据接口文档可以知道，返回值需要带上一个isNew字段，这个字段是给前端用来判断是新用户还是就用户的
        boolean isNew = false;

        // 第四步：查询当前手机号是否存在
        User userInfo = userService.getUserByPhone(phone);
        if (Objects.isNull(userInfo)) {
            // 第5.1步：注册
            userInfo = userService.createUserByPhone(phone);
            isNew = true;
        }

        if (Objects.isNull(userInfo)) {
            throw new Exception("用户注册失败");
        }

        // 第5.2步，生成token
        Map<String, Object> map = new HashMap<>(2);
        map.put("phone", userInfo.getMobile());
        map.put("userId", userInfo.getId());

        System.out.println(map);
        // jwt token包含三个部分
        // 1. header 加密方式
        // 2. 载荷   不敏感信息
        // 3. 签名    1+2 加密

        String token = JwtUtils.getToken(map);

        LoginVerificationVo vo = new LoginVerificationVo();
        vo.setIsNew(isNew);
        vo.setToken(token);

        return ResponseEntity.status(HttpStatus.OK).body(vo);
    }

    @PostMapping("/loginReginfo")
    public ResponseEntity loginReginfo(@RequestBody LoginReginfoDto dto) {

        // 获取token
        // 根据token获得我当前id
        String userId = TokenHolder.getUserId();

        // 前提：我第一次进入APP,使用手机号登录，数据库里user表已经存在我的手机
        // 2.要做什么？ 要往数据库user_info表里面加入我的信息，并且关联user表记录
        // 3.根据要做的事情，先把对应的数据库方法写出来
        // 4.根据数据库方法的入参，去寻找对应的数据

        // 这一步要判空，否则调用BeanUtils.copyProperties时会空指针
        if (Objects.isNull(dto)) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
        }

        // 将dto和userInfo两个对象进行比对，将两个对象中相同的变量进行赋值，前面赋值给后面
        UserInfo userInfo = new UserInfo();
        BeanUtils.copyProperties(dto, userInfo);

        // 获取当前请求接口的用户id，并且写入到userInfo
        userInfo.setId(userId);

        // 调用Service执行数据库插入
        UserInfo result = userService.createUserInfo(userInfo);
        return Objects.nonNull(result) ? ResponseEntity.ok(null) : ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("用户创建阿失败");
    }

    @PostMapping("/loginReginfo/head")
    public ResponseEntity loginReginfoHead(MultipartFile headPhoto) throws IOException {
        // 步骤一：判空
        if (Objects.isNull(headPhoto)) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("头像不能为空");
        }

        // 步骤二：获取文件大小，判断是否超过上传上限
        long size = headPhoto.getSize();
        if (size > 2097152) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("头像不能超过2M");
        }

        // 步骤三：获取文件类型，结果格式 images/png
        String contentType = headPhoto.getContentType();
        if (StringUtils.isEmpty(contentType)) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("头像不能为空");
        }

        String suffixName = contentType.split("/")[1];

        // 步骤四：执行上传
        String upload = ossTemplate.upload(suffixName, headPhoto.getInputStream());

        System.out.println(upload);

        // 步骤五：百度人脸识别
        boolean detect = aipTemplate.detect(upload);
        if (!detect) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("请上传真实头像");
        }

        UserInfo userInfo = new UserInfo();
        userInfo.setId(TokenHolder.getUserId());
        userInfo.setAvatar(upload);

        // 步骤六：更新用户信息
        Boolean updateResult = userService.updateUserInfo(userInfo);

        return updateResult ? ResponseEntity.ok(null) : ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
    }





}
